home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUT03NEW.ZIP / TUT3.TXT < prev   
Text File  |  1994-12-07  |  16KB  |  517 lines

  1.                    ╒═══════════════════════════════╕
  2.                    │         W E L C O M E         │
  3.                    │  To the VGA Trainer Program   │ │
  4.                    │              By               │ │
  5.                    │      DENTHOR of ASPHYXIA      │ │ │
  6.                    │      (updated by Snowman)     │ │ │
  7.                    ╘═══════════════════════════════╛ │ │
  8.                      ────────────────────────────────┘ │
  9.                        ────────────────────────────────┘
  10.  
  11.                            --==[ PART 3 ]==--
  12.  
  13.  
  14. [Note: things in brackets have been added by Snowman.  The original text
  15. has remained mostly unaltered except for the inclusion of C++ material]
  16.  
  17. ■ Introduction
  18.  
  19. Greetings! This is the third part of the VGA Trainer series! Sorry it 
  20. took so long to get out, but I had a running battle with the traffic
  21. department for three days to get my car registered, and then the MailBox
  22. went down. Ahh, well, life stinks. Anyway, today will do some things
  23. vital to most programs : Lines and circles.
  24.  
  25. Watch out for next week's part : Virtual screens. The easy way to
  26. eliminate flicker, "doubled sprites", and subjecting the user to watch
  27. you building your screen. Almost every ASPHYXIA demo has used a virtual
  28. screen (with the exception of the SilkyDemo), so this is one to watch out
  29. for. I will also show you how to put all of these loose procedures into
  30. units.
  31.  
  32. If you would like to contact me, or the team, there are many ways you 
  33. can do it : 1) Write a message to Grant Smith in private mail here on
  34.                   the Mailbox BBS.
  35.             2) Write a message here in the Programming conference here
  36.                   on the Mailbox (Preferred if you have a general
  37.                   programming query or problem others would benefit from)
  38.             3) Write to ASPHYXIA on the ASPHYXIA BBS.
  39.             4) Write to Denthor, Eze or Livewire on Connectix.
  40.             5) Write to :  Grant Smith
  41.                            P.O.Box 270 Kloof
  42.                            3640
  43.             6) Call me (Grant Smith) at 73 2129 (leave a message if you 
  44.                   call during varsity)
  45.                   
  46. NB : If you are a representative of a company or BBS, and want ASPHYXIA 
  47.        to do you a demo, leave mail to me; we can discuss it.
  48. NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
  49.         quite lonely and want to meet/help out/exchange code with other demo
  50.         groups. What do you have to lose? Leave a message here and we can work
  51.         out how to transfer it. We really want to hear from you!
  52.  
  53.  
  54. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  55. ■  Circle Algorithim
  56.  
  57. You all know what a circle looks like. But how do you draw one on the
  58. computer?
  59.  
  60. You probably know circles drawn with the degrees at these points :
  61.  
  62.                                 0
  63.                               ▄█|█▄
  64.                              ███|███
  65.                         270 ----+---- 90
  66.                              ███|███
  67.                               ▀█|█▀
  68.                                180
  69.  
  70. Sorry about my ASCII ;-) ... anyway, Pascal and C++ don't work that way ...
  71. they work with radians instead of degrees. (You can convert radians to
  72. degrees, but I'm not going to go into that now. Note though that in Pascal
  73. and C++, the circle goes like this :
  74.  
  75.                                270
  76.                               ▄█|█▄
  77.                              ███|███
  78.                         180 ----+---- 0
  79.                              ███|███
  80.                               ▀█|█▀
  81.                                 90
  82.  
  83.  
  84. Even so, we can still use the famous equations to draw our circle ...
  85. (You derive the following by using the theorem of our good friend
  86. Pythagoras)
  87.                      Sin (deg) = Y/R
  88.                      Cos (deg) = X/R
  89. (This is standard 8(?) maths ... if you haven't reached that level yet,
  90. take this to your dad, or if you get stuck leave me a message and I'll
  91. do a bit of basic Trig with you. I aim to please ;-))
  92.  
  93. Where Y = your Y-coord
  94.       X = your X-coord
  95.       R = your radius (the size of your circle)
  96.       deg = the degree
  97.  
  98. To simplify matters, we rewrite the equation to get our X and Y values :
  99.  
  100.                      Y = R*Sin(deg)
  101.                      X = R*Cos(deg)
  102.  
  103. This obviousy is perfect for us, because it gives us our X and Y co-ords to
  104. put into our Putpixel routine (see Part 1). Because the Sin and Cos
  105. functions return a Real [long] value, we use a round function to transform
  106. it into an Integer.
  107.  
  108. [Pascal]
  109.  
  110.      Procedure Circle (oX,oY,rad:integer;Col:Byte);
  111.      VAR deg:real;
  112.          X,Y:integer;
  113.      BEGIN
  114.        deg:=0;
  115.        repeat
  116.          X:=round(rad*COS (deg));
  117.          Y:=round(rad*sin (deg));
  118.          putpixel (x+ox,y+oy,Col);
  119.          deg:=deg+0.005;
  120.        until (deg>6.4);
  121.      END;
  122.  
  123. [C++]
  124.  
  125.      void Circle(int X, int Y, int rad, int col) {
  126.  
  127.        float deg = 0;
  128.  
  129.        do {
  130.          X = round(rad * cos(deg));
  131.          Y = round(rad * sin(deg));
  132.          Putpixel (X+160, Y+100, col);
  133.          deg += 0.005;
  134.        }
  135.        while (deg <= 6.4);
  136.  
  137.      }
  138.  
  139. In the above example, the smaller the amount that deg is increased by,
  140. the closer the pixels in the circle will be, but the slower the procedure.
  141. 0.005 seem to be best for the 320x200 screen. NOTE : ASPHYXIA does not use
  142. this particular circle algorithm, ours is in assembly language, but this
  143. one should be fast enough for most. If it isn't, give us the stuff you are
  144. using it for and we'll give you ours.
  145.  
  146.  
  147. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  148. ■  Line algorithms
  149.  
  150. There are many ways to draw a line on the computer. I will describe one
  151. and give you two. (The second one you can figure out for yourselves; it
  152. is based on the first one but is faster)
  153.  
  154. The first thing you need to do is pass what you want the line to look
  155. like to your line procedure. What I have done is said that x1,y1 is the
  156. first point on the screen, and x2,y2 is the second point. We also pass the
  157. color to the procedure. (Remember the screens top left hand corner is (0,0);
  158. see Part 1)
  159.  
  160. Ie.            o  (X1,Y1)
  161.                 ooooooooo
  162.                          ooooooooo
  163.                                   oooooooo  (X2,Y2)
  164.  
  165. Again, sorry about my drawings ;-)
  166.  
  167. To find the length of the line, we say the following :
  168.  
  169. [Pascal]
  170.  
  171.            XLength = ABS (x1-x2)
  172.            YLength = ABS (y1-y2)
  173.  
  174. [C++]
  175.  
  176.            xlength = abs(x1-x2);
  177.            ylength = abs(y1-y2);
  178.  
  179. The ABS function means that whatever the result, it will give you an
  180. absolute, or posotive, answer. At this stage I set a variable stating
  181. wheter the difference between the two x's are negative, zero or posotive.
  182. (I do the same for the y's) If the difference is zero, I just use a loop
  183. keeping the two with the zero difference posotive, then exit.
  184.  
  185. If neither the x's or y's have a zero difference, I calculate the X and Y
  186. slopes, using the following two equations :
  187.  
  188. [Pascal]
  189.  
  190.            Xslope = Xlength / Ylength
  191.            Yslope = Ylength / Xlength
  192.  
  193. [C++]
  194.  
  195. [Note: C++ is significantly different here.  I had to add special divide
  196. by zero checking.  C++ doesn't like x/0.  I also added in type-casting
  197. which might not have been necessary.  :)]
  198.  
  199.            if ((xlength != 0) && (ylength != 0)) {
  200.              xslope = (float)xlength/(float)ylength;
  201.              yslope = (float)ylength/(float)xlength;
  202.            }
  203.            else {
  204.              xslope = 0.0;
  205.              yslope = 0.0;
  206.            }
  207.  
  208. As you can see, the slopes are real numbers.
  209. NOTE : XSlope = 1 / YSlope
  210.  
  211. Now, there are two ways of drawing the lines :
  212.  
  213.            X = XSlope * Y
  214.            Y = YSlope * X
  215.  
  216. The question is, which one to use? if you use the wrong one, your line
  217. will look like this :
  218.  
  219.         o
  220.            o
  221.               o
  222.  
  223. Instead of this :
  224.  
  225.         ooo
  226.            ooo
  227.               ooo
  228.  
  229. Well, the solution is as follows :
  230.  
  231.                            *\``|``/*
  232.                            ***\|/***
  233.                            ----+----
  234.                            ***/|\***
  235.                            */``|``\*
  236.  
  237. If the slope angle is in the area of the stars (*) then use the first
  238. equation, if it is in the other section (`) then use the second one.
  239. What you do is you calculate the variable on the left hand side by
  240. putting the variable on the right hand side in a loop and solving. Below
  241. is our finished line routine :
  242.  
  243. [Pascal]
  244.  
  245. Procedure Line (x1,y1,x2,y2:integer;col:byte);
  246. VAR x,y,xlength,ylength,dx,dy:integer;
  247.     xslope,yslope:real;
  248. BEGIN
  249.   xlength:=abs (x1-x2);
  250.   if (x1-x2)<0 then dx:=-1;
  251.   if (x1-x2)=0 then dx:=0;
  252.   if (x1-x2)>0 then dx:=+1;
  253.   ylength:=abs (y1-y2);
  254.   if (y1-y2)<0 then dy:=-1;
  255.   if (y1-y2)=0 then dy:=0;
  256.   if (y1-y2)>0 then dy:=+1;
  257.   if (dy=0) then BEGIN
  258.     if dx<0 then for x:=x1 to x2 do
  259.       putpixel (x,y1,col);
  260.     if dx>0 then for x:=x2 to x1 do
  261.       putpixel (x,y1,col);
  262.     exit;
  263.   END;
  264.   if (dx=0) then BEGIN
  265.     if dy<0 then for y:=y1 to y2 do
  266.       putpixel (x1,y,col);
  267.     if dy>0 then for y:=y2 to y1 do
  268.       putpixel (x1,y,col);
  269.     exit;
  270.   END;
  271.   xslope:=xlength/ylength;
  272.   yslope:=ylength/xlength;
  273.   if (yslope/xslope<1) and (yslope/xslope>-1) then BEGIN
  274.     if dx<0 then for x:=x1 to x2 do BEGIN
  275.                    y:= round (yslope*x);
  276.                    putpixel (x,y,col);
  277.                  END;
  278.     if dx>0 then for x:=x2 to x1 do BEGIN
  279.                    y:= round (yslope*x);
  280.                    putpixel (x,y,col);
  281.                  END;
  282.   END
  283.   ELSE
  284.   BEGIN
  285.     if dy<0 then for y:=y1 to y2 do BEGIN
  286.                    x:= round (xslope*y);
  287.                    putpixel (x,y,col);
  288.                  END;
  289.     if dy>0 then for y:=y2 to y1 do BEGIN
  290.                    x:= round (xslope*y);
  291.                    putpixel (x,y,col);
  292.                  END;
  293.   END;
  294. END;
  295.  
  296. [C++]
  297.  
  298. void Line2(int x1, int y1, int x2, int y2, int col) {
  299.  
  300.   int   x, y, xlength, ylength, dx, dy;
  301.   float xslope, yslope;
  302.  
  303.   xlength = abs(x1-x2);
  304.   if ((x1-x2)  < 0) dx = -1;
  305.   if ((x1-x2) == 0) dx =  0;
  306.   if ((x1-x2)  > 0) dx = +1;
  307.  
  308.   ylength = abs(y1-y2);
  309.   if ((y1-y2)  < 0) dy = -1;
  310.   if ((y1-y2) == 0) dy =  0;
  311.   if ((y1-y2)  > 0) dy = +1;
  312.  
  313.   if (dy == 0) {
  314.     if (dx < 0)
  315.       for (x=x1; x<x2+1; x++)
  316.     Putpixel (x,y1,col);
  317.     if (dx > 0)
  318.       for (x=x2; x<x1+1; x++)
  319.     Putpixel (x,y1,col);
  320.   }
  321.  
  322.   if (dx == 0) {
  323.     if (dy < 0)
  324.       for (y=y1; y<y2+1; y++)
  325.     Putpixel (x1,y,col);
  326.     if (dy > 0)
  327.       for (y=y2; y<y1+1; y++)
  328.     Putpixel (x1,y,col);
  329.   }
  330.  
  331.   if ((xlength != 0) && (ylength != 0)) {
  332.     xslope = (float)xlength/(float)ylength;
  333.     yslope = (float)ylength/(float)xlength;
  334.   }
  335.   else {
  336.     xslope = 0.0;
  337.     yslope = 0.0;
  338.   }
  339.  
  340.   if ((xslope != 0) && (yslope != 0) &&
  341.       (yslope/xslope < 1) && (yslope/xslope > -1)) {
  342.     if (dx < 0)
  343.       for (x=x1; x<x2+1; x++) {
  344.     y = round (yslope*x);
  345.     Putpixel (x,y,col);
  346.       }
  347.     if (dx > 0)
  348.       for (x=x2; x<x1+1; x++) {
  349.     y = round (yslope*x);
  350.     Putpixel (x,y,col);
  351.       }
  352.   }
  353.   else {
  354.     if (dy < 0)
  355.       for (y=x1; y<x2+1; y++) {
  356.     x = round (xslope*y);
  357.     Putpixel (x,y,col);
  358.       }
  359.     if (dy > 0)
  360.       for (y=x2; y<x1+1; y++) {
  361.     x = round (xslope*y);
  362.     Putpixel (x,y,col);
  363.       }
  364.   }
  365.  
  366. }
  367.  
  368. Quite big, isn't it? Here is a much shorter way of doing much the same
  369. thing :
  370.  
  371. [Pascal]
  372.  
  373. function sgn(a:real):integer;
  374. begin
  375.      if a>0 then sgn:=+1;
  376.      if a<0 then sgn:=-1;
  377.      if a=0 then sgn:=0;
  378. end;
  379.  
  380. procedure line(a,b,c,d,col:integer);
  381. var u,s,v,d1x,d1y,d2x,d2y,m,n:real;
  382.     i:integer;
  383. begin
  384.      u:= c - a;
  385.      v:= d - b;
  386.      d1x:= SGN(u);
  387.      d1y:= SGN(v);
  388.      d2x:= SGN(u);
  389.      d2y:= 0;
  390.      m:= ABS(u);
  391.      n := ABS(v);
  392.      IF NOT (M>N) then
  393.      BEGIN
  394.           d2x := 0 ;
  395.           d2y := SGN(v);
  396.           m := ABS(v);
  397.           n := ABS(u);
  398.      END;
  399.      s := INT(m / 2);
  400.      FOR i := 0 TO round(m) DO
  401.      BEGIN
  402.           putpixel(a,b,col);
  403.           s := s + n;
  404.           IF not (s<m) THEN
  405.           BEGIN
  406.                s := s - m;
  407.                a:= a +round(d1x);
  408.                b := b + round(d1y);
  409.           END
  410.           ELSE
  411.           BEGIN
  412.                a := a + round(d2x);
  413.                b := b + round(d2y);
  414.           END;
  415.      end;
  416. END;
  417.  
  418. [C++]
  419.  
  420. int sgn (long a) {
  421.   if (a > 0) return +1;
  422.   else if (a < 0) return -1;
  423.   else return 0;
  424.  
  425. }
  426.  
  427. void Line(int a, int b, int c, int d, int col) {
  428.  
  429.   long u,s,v,d1x,d1y,d2x,d2y,m,n;
  430.   int  i;
  431.  
  432.   u   = c-a;
  433.   v   = d-b;
  434.   d1x = sgn(u);
  435.   d1y = sgn(v);
  436.   d2x = sgn(u);
  437.   d2y = 0;
  438.   m   = abs(u);
  439.   n   = abs(v);
  440.  
  441.   if (m<=n) {
  442.     d2x = 0;
  443.     d2y = sgn(v);
  444.     m   = abs(v);
  445.     n   = abs(u);
  446.   }
  447.  
  448.   s = (int)(m / 2);
  449.  
  450.   for (i=0;i<round(m);i++) {
  451.     Putpixel(a,b,col);
  452.     s += n;
  453.     if (s >= m) {
  454.       s -= m;
  455.       a += d1x;
  456.       b += d1y;
  457.     }
  458.     else {
  459.       a += d2x;
  460.       b += d2y;
  461.     }
  462.   }
  463.  
  464. }
  465.  
  466. This routine is very fast, and should meet almost all of your requirements
  467. (ASPHYXIA used it for quite a while before we made our new one.)
  468. In the end program, both the new line routine and the circle routine are
  469. tested. A few of the procedures of the first parts are also used.
  470.  
  471. Line and circle routines may seem like fairly trivial things, but they are
  472. a vital component of many programs, and you may like to look up other
  473. methods of drawing them in books in the library (I know that here at the
  474. varsity they have books for doing this kind of stuff all over the place)
  475. A good line routine to look out for is the Bressenhams line routine ...
  476. there is a Bressenhams circle routine too ... I have documentaiton for them
  477. if anybody is interested, they are by far some of the fastest routines
  478. you will use.
  479.  
  480. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  481. ■  In closing
  482.  
  483. Varsity has started again, so I am (shock) going to bed before three in
  484. the morning, so my quote this week wasn't written in the same wasted way
  485. my last weeks one was (For last week's one, I had gotten 8 hours sleep in
  486. 3 days, and thought up and wrote the quote at 2:23 am before I fell asleep.)
  487.  
  488.         [  "What does it do?" she asks.
  489.            "It's a computer," he replies.
  490.            "Yes, dear, but what does it do?"
  491.            "It ..er.. computes! It's a computer."
  492.            "What does it compute?"
  493.            "What? Er? Um. Numbers! Yes, numbers!" He smiles
  494.               worriedly.
  495.            "Why?"
  496.            "Why? Well ..um.. why?" He starts to sweat.
  497.            "I mean, is it just something to dust around, or does
  498.               it actually do something useful?"
  499.            "Um...you can call other computers with it!" Hope lights
  500.               up his eyes. "So you can get programs from other computers!"
  501.            "I see. Tell me, what do these programs do?"
  502.            "Do? I don't think I fol..."
  503.            "I see. They compute. Numbers. For no particular reason." He
  504.               withers under her gaze.
  505.            "Yes, but..."
  506.            She smiles, and he trails off, defeated. She takes another look
  507.                at the thing. "Although," she says, with a strange look in
  508.                her eyes. He looks up, an insane look of hope on his
  509.                face. "Does it come in pink?" she asks.
  510.                                                                            ]
  511.                                                      - Grant Smith
  512.                                                         Tue 27 July, 1993
  513.                                                          9:35 pm.
  514.  
  515. See you next time,
  516.     - Denthor
  517.